﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Convertor;

/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
public class NameValueCollectionConvertor<T> : AllowNullConvertor<T>, IFrom<object, T?>, IFrom<Dictionary<string, object>, T?>
    where T : NameValueCollection
{
    /// <summary>
    /// 转换器有错误
    /// </summary>
    private readonly bool _error;
    /// <summary>
    /// 转换器默认构造函数
    /// </summary>
    public NameValueCollectionConvertor() => _error = (OutputType.MatchType(typeof(NameValueCollection), typeof(NameValueCollection)) is not MacthedType.Equals and not MacthedType.Acceptable and not MacthedType.TryCreate);

    /// <inheritdoc />
    public ConvertResult<T?> From(IConvertContext context, object input)
    {
        if (_error)
        {
            return ExceptionHelper.InstantiationFail(TypeFriendlyName, context.Settings.CultureInfo);
        }
        var enumerator = new KeyValueEnumerator<string, string>(context, input);
        if (!enumerator.KeyIsString)
        {
            return context.ConvertFail(this, input);
        }
        var collection = context.Settings.CreateInstance<T>();
        while (enumerator.MoveNext())
        {
            var key = enumerator.GetKey();
            if (!key.Success)
            {
                return ExceptionHelper.CollectionKeyFail(TypeFriendlyName, enumerator.OriginalKey + "", context.Settings.CultureInfo);
            }

            var value = enumerator.GetValue();
            if (!value.Success)
            {
                return ExceptionHelper.CollectionAddFail(TypeFriendlyName, key.Value!, enumerator.OriginalValue, context.Settings.CultureInfo);
            }

            collection.Add(key.Value, value.Value);
        }
        return collection;
    }

    /// <inheritdoc />
    public ConvertResult<T?> From(IConvertContext context, Dictionary<string, object> input) => From(context, (object)input);
}
